package commons.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import commons.entity.DD;
import commons.entity.InMyMouse;
import commons.entity.NativeCp;
import fgoScript.constant.GameConstant;
import fgoScript.constant.PointInfo;
import fgoScript.entity.BaseZButton;
import fgoScript.entity.ColorMonitor;
import fgoScript.entity.PointColor;
import fgoScript.entity.panel.FgoFrame;
import fgoScript.entity.panel.SetupClickPanel;
import fgoScript.exception.AppNeedRestartException;
import fgoScript.exception.AppNeedStopException;
import fgoScript.exception.AppNeedUpdateException;
import fgoScript.service.AutoAct;
import fgoScript.service.TimerManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.List;
import java.util.*;
import java.util.concurrent.*;

public class GameUtil {
	private static final Logger LOGGER = LogManager.getLogger(GameUtil.class);
	private static final int OUT_TIME = Integer.parseInt(GameUtil.getValueFromConfig("OUT_TIME"));// 超时时间(分)
	private static final int CHECK_TIMES = Integer.parseInt(GameUtil.getValueFromConfig("CHECK_TIMES"));
	private static final int EROOR_ROUND = 8;// 循环检查系数(DELAY*X*Y)
	private static boolean GO_FLAG = true;
	private static int CHECK_COUNT = 0;// 检测基数
	public static boolean STOP_SCRIPT = false;
	private static boolean FORCE_OUTTIME = false;
	private static boolean WAIT_FLAG = false;
	private static int OUTTIME_COUNT = 0;
	private static int WAIT_COUNT = 0;
	private static Random ran = new Random(2);
	private static Object lock = new Object();
	private static InMyMouse im;
	private static Robot rb=(Robot) MySpringUtil.getApplicationContext().getBean("rb");
	private static Map<String, Robot> rbMap = new HashMap<>();
	public static List<ColorMonitor> colorMonitorList;
	public static Robot getRb(){
		if(rb==null){
			rb = (Robot) MySpringUtil.getApplicationContext().getBean("rb");
		}
		return rb;
	}
	public static SetupClickPanel getSetupClickPanel(){
		ClassPathXmlApplicationContext applicationContext = MySpringUtil.getApplicationContext();
		SetupClickPanel s = (SetupClickPanel) applicationContext.getBean("setupClickPanel");
		return s;
	}
	public static Point getMousePosition() {
		PointerInfo pinfo = MouseInfo.getPointerInfo();
		return pinfo.getLocation();
	}
	public static InMyMouse getMymouse(){
		if(im==null){
			im = (InMyMouse) MySpringUtil.getApplicationContext().getBean("myMouse");
		}
		return im;
	};
	public static Color getScreenPixel(Point p) {
		return rb.getPixelColor((int) p.getX(), (int) p.getY());
	}

	public static void setRb(Robot r) {
		rb = r;
	}
	
	public static boolean isWAIT_FLAG() {
		return WAIT_FLAG;
	}
	public static String ConvertSecondsToHMS(int totalSeconds){
		int hours = totalSeconds / 3600;
		int minutes = (totalSeconds % 3600) / 60;
		int seconds = totalSeconds % 60;
		String text = (hours==0?"":hours+"小时")+(minutes==0?"":minutes+"分")+seconds+"秒";
		return text;
	}
	public static boolean isBlank(String fileName) {
		return fileName == null || fileName.trim().isEmpty();
	}
	public static File createUniqueFile(String directoryPath, String fileName) throws IOException {
		File directory = new File(directoryPath);
		if (!directory.exists()) {
			directory.mkdirs(); // 创建目录
		}
		// 创建新文件
		File file = new File(directory, fileName.trim());
		if (file.exists()) {
			ProcessDealUtil.displayTray("文件名重复","请重新命名！", TrayIcon.MessageType.WARNING);
			throw new IOException("File already exists: " + file.getAbsolutePath());
		}
		if (file.createNewFile()) {
			return file;
		} else {
			throw new IOException("Could not create file: " + file.getAbsolutePath());
		}
	}
	public static String getNowDateString(){
		LocalDate today = LocalDate.now();
		int year = today.getYear();
		int month = today.getMonthValue();
		int day = today.getDayOfMonth();
		return year+"年"+month+"月"+day+"日";
	}
	public static void waitOrContinue(BaseZButton zt) {
		if (WAIT_COUNT++%2 ==0) {
			WAIT_FLAG = true;
			zt.setText("继续");
		}else {
			synchronized (getLock()) {
				WAIT_FLAG = false;
				lock.notifyAll();
			}
			zt.setText("暂停");
		}
	}
	public static void ifPauseScript(){
		if (isWAIT_FLAG()) {
			Object lock;
			synchronized (lock = GameUtil.getLock()) {
				LOGGER.info("程序暂停运行!");
				try {
					lock.wait();
				} catch (InterruptedException e) {
					LOGGER.error(e.getMessage(),e);
				}
				GameUtil.setWAIT_FLAG(false);
				LOGGER.info("程序继续运行!");
			}
		}
	}
	public static void shutDownALl() {
		synchronized (getLock()) {
			WAIT_FLAG = false;
			lock.notifyAll();
		}
		setSTOP_SCRIPT(true);
	}
	public static void setWAIT_FLAG(boolean wAIT_FLAG) {
		WAIT_FLAG = wAIT_FLAG;
	}
	public static Object getLock() {
		if (lock == null) {
			lock = new Object();
		}
		return lock;
	}
	public static void setLock(Object lock) {
		GameUtil.lock = lock;
	}
	public static boolean isFORCE_OUTTIME() {
		return FORCE_OUTTIME;
	}
	public static void setFORCE_OUTTIME(boolean fORCE_OUTTIME) {
		FORCE_OUTTIME = fORCE_OUTTIME;
	}
	public static boolean isSTOP_SCRIPT() {
		return STOP_SCRIPT;
	}
	public static void setSTOP_SCRIPT(boolean sTOP_SCRIPT) {
		STOP_SCRIPT = sTOP_SCRIPT;
	}
	public static int getCHECK_COUNT() {
		return CHECK_COUNT;
	}
	public static void setCHECK_COUNT(int cHECK_COUNT) {
		CHECK_COUNT = cHECK_COUNT;
	}
	public static boolean isGO_FLAG() {
		return GO_FLAG;
	}
	public static void setGO_FLAG(boolean gO_FLAG) {
		GO_FLAG = gO_FLAG;
	}
	private static PointColor waitUntilOneColorInner(List<PointColor> pocoList, String monitorName) throws AppNeedUpdateException, AppNeedRestartException, AppNeedStopException, InterruptedException {
//		setSTOP_SCRIPT(false);
		GO_FLAG = true;
		boolean flag;
		PointColor returnPC = null;
		Point p;
		Color c0;
		Color c1;
		boolean isEqual;
		int count = 0;
		int check = 0;

		StringBuilder Str = new StringBuilder();
		int size = pocoList.size();
		PointColor pointColor;
		for (int i = 0; i < size; i++) {
			pointColor = pocoList.get(i);
			Color c = pointColor.getColor();
			Str.append(c.getRed()).append(":").append(c.getGreen()).append(":").append(c.getBlue()).append("_");
		}
		LOGGER.debug("当前等待颜色组：" + Str);
		do {
			for (int i = 0; i < size; i++) {
				pointColor = pocoList.get(i);
				p = pointColor.getPoint();
				c0 = pointColor.getColor();
				isEqual = pointColor.isEqual();
				c1 = GameUtil.getScreenPixel(p);
				flag = likeEqualColor(c1, c0);
				if (!isEqual) {
					flag = !flag;
				}
				if (flag) {
					LOGGER.debug("等待的颜色结果： " + c0.getRed() + ":" + c0.getGreen() + ":" + c0.getBlue());
					count++;
					returnPC = pointColor;
				}
			}
			// 意外检查
			if (check != 0 && (count == 0) && (check % EROOR_ROUND == 0)) {
				waitInteruptSolution(check, monitorName);
			}
			check++;
			Thread.sleep(GameConstant.DELAY*CHECK_TIMES);
			if (!GO_FLAG && CHECK_COUNT == 0) {
				return null;
			}
			if (STOP_SCRIPT) {
				throw new AppNeedStopException();
			}
			if (FORCE_OUTTIME) {
				setFORCE_OUTTIME(false);
				throw new AppNeedRestartException();
			}
			if (isWAIT_FLAG()) {
				synchronized (getLock()) {
					LOGGER.info("程序暂停运行!");
					lock.wait();
					LOGGER.info("程序继续运行!");
				}
			}
		} while (count == 0);
		CHECK_COUNT++;
		return returnPC;
	}
	/**
	 * @Description: 等待颜色
	 * @param pocoList PointColor对象集合
	 * @return: fgoScript.entity.PointColor
	 * @Author: RENZHEHAO
	 * @Date: 2019/6/5
	 */
	public static PointColor waitUntilOneColor(List<PointColor> pocoList, String monitorName) throws AppNeedUpdateException, AppNeedRestartException, AppNeedStopException {
		PointColor returnPC = null;
		Callable<PointColor> task = () -> {
			PointColor pc =  waitUntilOneColorInner(pocoList, monitorName);
			return pc;
		};
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		Future<PointColor> future = executorService.submit(task);
		
		try {
			future.get(OUT_TIME, TimeUnit.MINUTES);
			returnPC = future.get();
		}catch (TimeoutException e) {
			boolean flag;
			flag = future.cancel(true);
			LOGGER.info("超时了" + "_" + flag);
			if (OUTTIME_COUNT-->0 || isWAIT_FLAG()) {
				if (isWAIT_FLAG()) {
					LOGGER.info("延长超时！原因：线程需要暂停运行");
				}else {
					LOGGER.info("延长超时！原因：线程需要继续运行");
				}
				returnPC = waitUntilOneColor(pocoList, monitorName);
			}else {
				throw new AppNeedRestartException();
			}
		} catch (InterruptedException e) {
			LOGGER.info("终止了颜色检测程序！");
		} catch (ExecutionException e) {
			if (e.getCause() instanceof AppNeedRestartException) {
				throw new AppNeedRestartException();
			}else if(e.getCause() instanceof AppNeedStopException) {
				throw new AppNeedStopException();
			}else if(e.getCause() instanceof AppNeedUpdateException) {
				throw new AppNeedUpdateException();
			}
		} finally {
			OUTTIME_COUNT = 0;
			executorService.shutdown();
		}
		
		return returnPC;
	}

	public static void waitUntilAllColor(List<PointColor> pocoList, int delay, String monitorName) throws AppNeedUpdateException, AppNeedRestartException, AppNeedStopException {
		Callable<String> task = () -> {
			waitUntilAllColorInner(pocoList, delay, monitorName);
			return null;
		};
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		Future<String> future = executorService.submit(task);
		try {
			future.get(OUT_TIME, TimeUnit.MINUTES);
		} catch (TimeoutException e) {
			boolean flag;
			flag = future.cancel(true);
			LOGGER.info("超时了" + "_" + flag);
			if (OUTTIME_COUNT-->0 || isWAIT_FLAG()) {
				if (isWAIT_FLAG()) {
					LOGGER.info("延长超时！原因：线程需要暂停运行");
				}else {
					LOGGER.info("延长超时！原因：线程需要继续运行");
				}
				waitUntilAllColor(pocoList, delay, monitorName);
			}else {
				throw new AppNeedRestartException();
			}
		} catch (InterruptedException e) {
			LOGGER.info("终止了颜色检测程序！");
		} catch (ExecutionException e) {
			if (e.getCause() instanceof AppNeedRestartException) {
				throw new AppNeedRestartException();
			}else if(e.getCause() instanceof AppNeedStopException) {
				throw new AppNeedStopException();
			}
		} finally {
			OUTTIME_COUNT = 0;
			executorService.shutdown();
		}
	}

	private static void waitUntilAllColorInner(List<PointColor> pocoList, int delay, String monitorName) throws AppNeedUpdateException, AppNeedRestartException, AppNeedStopException, InterruptedException {
		setSTOP_SCRIPT(false);
		boolean flag;
		Point p;
		Color c0;
		Color c1;
		boolean isEqual;
		int count;
		int check = 0;
		boolean toCheck;

		StringBuilder Str = new StringBuilder();
		int size = pocoList.size();
		PointColor pointColor;
		for (int i = 0; i < size; i++) {
			pointColor = pocoList.get(i);
			Color c = pointColor.getColor();
			Str.append(c.getRed()).append(":").append(c.getGreen()).append(":").append(c.getBlue()).append("_");
		}
		LOGGER.debug("当前等待颜色组：" + Str);
		do {
			count = 0;
			for (int i = 0; i < size; i++) {
				pointColor =pocoList.get(i);
				p = pointColor.getPoint();
				c0 = pointColor.getColor();
				isEqual = pointColor.isEqual();
				c1 = GameUtil.getScreenPixel(p);
				flag = likeEqualColor(c1, c0);
				if (!isEqual) {
					flag = !flag;
				}
				if (flag) {
					count++;
				}
			}
			toCheck = (count == pocoList.size());
			// 异常检查
			if ((!toCheck) && (check % EROOR_ROUND == 0)) {
				waitInteruptSolution(check, monitorName);
			}
			check++;
			Thread.sleep(delay*CHECK_TIMES);
			if (STOP_SCRIPT) {
				throw new AppNeedStopException();
			}
			if (FORCE_OUTTIME) {
				setFORCE_OUTTIME(false);
				throw new AppNeedRestartException();
			}
			if (isWAIT_FLAG()) {
				if (lock != null) {
					synchronized (getLock()) {
						LOGGER.info("程序暂停运行!");
						lock.wait();
						LOGGER.info("程序继续运行!");
					}
				}
			}
		} while (!toCheck);
		LOGGER.debug("所有颜色组匹配成功");
	}
	public static String getJsonString(String path){
		BufferedReader reader = null;
		InputStream inputStream=null;
		StringBuilder jsonStrs = new StringBuilder();
		try {
			inputStream = new FileInputStream(path);
			if(inputStream==null){
				LOGGER.info(path+" is not exist or the json file is wrong");
			}
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
			reader = new BufferedReader(inputStreamReader);
			String tempStr = null;
			while ((tempStr = reader.readLine()) != null) {
				jsonStrs.append(tempStr);
			}
			reader.close();
		} catch (IOException e) {
			LOGGER.error(e.getMessage(),e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					LOGGER.error(e.getMessage(),e);
				}
			}
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					LOGGER.error(e.getMessage(),e);
				}
			}
		}
		return jsonStrs.toString().trim();
	}
	public static JSONArray ConvertToJsonArray(String path){

		JSONArray jsonArray =null;
		BufferedReader reader = null;
		StringBuilder jsonStrs = new StringBuilder();

		try{
			jsonArray=JSONArray.parseArray(getJsonString(path));
		}catch(IllegalStateException ex){
			LOGGER.error(path+"JSON  File is wrong");
		}catch(JSONException ex){
			LOGGER.error(path+"JSON  File is wrong");
		}
		return jsonArray;
	}
	public static JSONObject ConvertToJSONObject(String path){

		JSONObject jSONObject =null;
		BufferedReader reader = null;
		StringBuilder jsonStrs = new StringBuilder();

		try{
			jSONObject=JSONObject.parseObject(getJsonString(path));
		}catch(IllegalStateException ex){
			LOGGER.error(path+"JSON  File is wrong");
		}catch(JSONException ex){
			LOGGER.error(path+"JSON  File is wrong");
		}
		return jSONObject;
	}
	private static List<ColorMonitor> getColorMonitorList(String monitorName){
		String filepath = System.getProperty("user.dir") + "/config/"+ monitorName +".json";
		JSONArray monitorJsonArray = ConvertToJsonArray(filepath);

		int size = monitorJsonArray.size();
		ColorMonitor colorMonitor;
		List<ColorMonitor> colorMonitorList= new ArrayList<>();
		for (int i = 0; i < size; i++) {
			colorMonitor = JSONArray.parseObject(monitorJsonArray.getJSONObject(i).toJSONString(), ColorMonitor.class);
			colorMonitorList.add(colorMonitor);
		}
		return colorMonitorList;
	}
	public static void waitInteruptSolution(int check, String monitorName) throws AppNeedRestartException, AppNeedUpdateException, AppNeedStopException {
		if (colorMonitorList == null || check == 0) {
			colorMonitorList = getColorMonitorList(monitorName);
		}
		int size = colorMonitorList.size();
		ColorMonitor cm;
		List<PointColor> checkPcList;
		int checkPcListSize;
		List<Point> clickPointList;
		int clickPointListSize;
		int count;
		Point tempPoint;
		for (int i = 0; i < size; i++) {
			cm = colorMonitorList.get(i);
			checkPcList = cm.getCheckPointList();
			checkPcListSize = checkPcList.size();
			count = ColorMatchCount(checkPcList);
			if (count == checkPcListSize) {
				GameUtil.delay(1000);
				count = ColorMatchCount(checkPcList);
				if(count == checkPcListSize){
					clickPointList = cm.getClickPointList();
					clickPointListSize = clickPointList.size();
					for (int j = 0; j < clickPointListSize; j++) {
						tempPoint = clickPointList.get(j);

						GameUtil.getMymouse().mouseMoveByPoint(tempPoint,true,true);


						GameUtil.getMymouse().mousePressAndRelease(GameConstant.DELAY/4);
						LOGGER.info(cm.getName());
					}
					if (cm.isExtendOutTime()){
						OUTTIME_COUNT = Integer.parseInt(GameUtil.getValueFromConfig("OUTTIME_COUNT"));
					}
					if (cm.isThrowException()){
						delay(5000);
						AppNeedRestartException ar = new AppNeedRestartException();
						ar.setName(cm.getName());
						throw ar;
					}
					if (cm.isNeedUpdate()){
						delay(5000);
						throw new AppNeedUpdateException();
					}
				}
			}
		}
	}

	public static int ColorMatchCount(List<PointColor> pocoList) {
		Color temp;
		PointColor pc;
		Point p;
		Color c;
		int count = 0;
		boolean result;
		for (int i = 0; i < pocoList.size(); i++) {
			pc = pocoList.get(i);
			p = pc.getPoint();
			c = pc.getColor();
			temp = GameUtil.getScreenPixel(p);
			result = likeEqualColor(c, temp);
			if (!pc.isEqual()) {
				result = !result;
			}
			if (result) {
				count++;
			}
		}
		return count;
	}

	public static int getColorEveValue(List<Point> pointList) {
		Point p;
		Color c;
		int addtion = 0;
		for (int i = 0; i < pointList.size(); i++) {
			p = pointList.get(i);
			c = GameUtil.getScreenPixel(p);
			addtion += c.getRed() + c.getGreen() + c.getBlue();
		}
		return (int) addtion / (pointList.size() * 3);
	}

	public static int ColorMatchCountProper(List<PointColor> pocoList) {
		Color temp;
		PointColor pc;
		Point p;
		Color c;
		int count = 0;
		boolean result;
		for (int i = 0; i < pocoList.size(); i++) {
			pc = pocoList.get(i);
			p = pc.getPoint();
			c = pc.getColor();
			temp = GameUtil.getScreenPixel(p);
			// 颜色误差
			int DIS_NUM = 25;
			result = Math.abs((c.getRed() + c.getGreen() + c.getBlue() - temp.getRed() - temp.getGreen()
					- temp.getBlue())) < DIS_NUM;
			if (!pc.isEqual()) {
				result = !result;
			}
			if (result) {
				count++;
			}
		}
		return count;
	}

	/**
	 * 
	 * @param extent
	 *            格式(jpg、png)
	 * @param newfile
	 *            test1.jpg
	 */
	public static void img2file(String extent, String newfile) {
		Rectangle rec = new Rectangle(45, 54, 1280, 720);
		Img2file(rec, extent, newfile);
	}
	public static void img2fileForTopToon(String extent, String newfile) {
		Rectangle rec = new Rectangle(453, 123, 1000, 900);
		Img2file(rec, extent, newfile);
	}
	public static void fullScreen2file(String extent, String newfile) {
		Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
		int width = (int) d.getWidth();
		int height = (int) d.getHeight();
		Rectangle rec = new Rectangle(0, 0, width, height);
		Img2file(rec, extent, newfile);
	}
	private static void Img2file(Rectangle rec, String extent, String newfile) {
		try {
			// Toolkit tk = Toolkit.getDefaultToolkit(); // 获取缺省工具包
			// Dimension di = tk.getScreenSize(); // 屏幕尺寸规格
			File file = new File(newfile + extent);
			if (!file.exists()) {
				file.mkdirs();
			}
			BufferedImage bi = rb.createScreenCapture(rec);
			ImageIO.write(bi, extent, file);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(),e);
		}
	}
//	public static void mouseMoveByPoint(Point p) throws AppNeedStopException {
//		   if(GameUtil.STOP_SCRIPT){
//		   	 GameUtil.STOP_SCRIPT = false;
//		   	 throw new AppNeedStopException();
//		   }
//			mouseMoveByDDRadom((int) p.getX(), (int) p.getY());
//			rb.delay(GameConstant.DELAY);
//	}
//    public static void mouseMoveByPointAcurate(Point p) {
//        mouseMoveByDDAcurate((int) p.getX(), (int) p.getY());
//        rb.delay(GameConstant.DELAY);
//    }
//	public static void mouseMoveByPointAcurateNoDelay(Point p) {
////		mouseMoveByDDAcurate((int) p.getX(), (int) p.getY());
////
////	}
//	public static void mouseMoveByPointAcurateNoDelayByRobot(Point p) {
//		mouseMoveByRobotAcurate((int) p.getX(), (int) p.getY());
//
//	}

//	public static void mousePressAndRelease(int key) {
//
//			dd.HIVM_BTN(1);
//			rb.delay(GameConstant.DELAY/4);
//			dd.HIVM_BTN(2);
//			rb.delay(GameConstant.DELAY);
//			rb.delay(GameConstant.DELAY);
//
//
//	}
//	public static void mousePressAndRelease(int key, int delaly) {
//		dd.HIVM_BTN(1);
//		rb.delay(delaly);
//		dd.HIVM_BTN(2);
//	}

//	public static void mousePressByRobert() {
//		rb.mousePress(InputEvent.BUTTON1_MASK);
//	}
//	public static void mouseReleaseByRobert() {
//		rb.mouseRelease(InputEvent.BUTTON1_MASK);
//	}
//	public static void mousePressAndReleaseForConfirm(int key) throws AppNeedRestartException {
//		mousePressAndReleaseForConfirm(key, null);
//	}
	/* pc */
//	public static void mousePressAndReleaseForConfirm(int key, PointColor pc) throws AppNeedRestartException {
//		Point p;
//		Color c;
//		boolean isEqual;
//		if (pc==null) {
//			p = MouseInfo.getPointerInfo().getLocation();
//			c = GameUtil.getScreenPixel(p);
//			isEqual = true;
//		}else {
//			p = pc.getPoint();
//			c = pc.getColor();
//			isEqual = pc.isEqual();
//		}
//		Color colorBefore;
//		Color colorAfter;
//		int count =10;
//		boolean flag;
//		boolean flag2;
//		do {
//			colorBefore = GameUtil.getScreenPixel(p);
//			dd.HIVM_BTN(1);
//			rb.delay(GameConstant.DELAY/4);
//			dd.HIVM_BTN(2);
//			rb.delay(GameConstant.DELAY*4);
//			colorAfter = GameUtil.getScreenPixel(p);
//			flag = GameUtil.likeEqualColor(c, colorAfter);
//			flag2 = GameUtil.likeEqualColor(colorBefore, colorAfter);
//			if (pc == null) {
//				flag = flag || flag2;
//			}else {
//				if (isEqual) {
//					flag = !flag;
//				}
//			}
//			if (count-- < 0) {
//				throw new AppNeedRestartException();
//			}
//		} while (flag);
//
//	}
	public static void waitForHomePage() throws Exception {
		GameUtil.delay(GameConstant.DELAY * 5);
		// 公告×点
		Point p_notice_exit = PointInfo.getInstance().getpNoticeExit();
		Color c_notice_exit = PointInfo.getInstance().getcNoticeExit();
		// 公告×点
		Point p_notice_exit_dark = PointInfo.getInstance().getpNoticeExitDark();
		Color c_notice_exit_dark = PointInfo.getInstance().getcNoticeExitDark();
		// 盲点
		Point dead_point = PointInfo.getInstance().getDeadPoint();
		// 咕哒子
		Point p_guda = PointInfo.getInstance().getpGuda();
		Color c_guda = PointInfo.getInstance().getcGuda();
		//新加入点
		List<PointColor> open2GudaList = PointInfo.getInstance().getOpen2GudaList();
		List<PointColor> beforeFinishGudaList = PointInfo.getInstance().getBeforeFinishGudaList();
		int ogSize = open2GudaList.size();

		//遍历加入点
		List<PointColor> pcList = new ArrayList<>();
		for (int i = 0; i < ogSize; i++) {
			pcList.add(open2GudaList.get(i));
		}
		pcList.add(new PointColor(p_notice_exit, c_notice_exit, p_notice_exit, true));
		pcList.add(new PointColor(p_notice_exit_dark, c_notice_exit_dark, p_notice_exit_dark, true));
		List<PointColor> finishPCList = new ArrayList<>();
		finishPCList.add(new PointColor(p_guda, c_guda, dead_point, true));
		finishPCList.add(new PointColor(PointInfo.getInstance().getpBlueAttack(), PointInfo.getInstance().getcBlueAttack(), dead_point, true));

		AutoAct ac = new AutoAct(pcList, finishPCList,beforeFinishGudaList) {
			@Override
			public void doSomeThing() {
			}
		};
		ac.autoAct();
	}
//	public static void moveBySteps(Point start, Point end) {
//		int actor = end.getX() + end.getY() - start.getX() - start.getY() > 0 ? 1 : -1;
//		if ((int) start.getX() == (int) end.getX()) {
//
//			for (int i = (int) start.getY(); (i - end.getY()) * actor < 0; i += GameConstant.MOVE_STEP * actor) {
//				rb.mouseMove((int) start.getX(), i);
//				if (i == (int) start.getY()) {
//					GameUtil.delay(GameConstant.DELAY);
//					mousePress();
//				}
//				rb.delay(GameConstant.MOVE_TIME);
//			}
//		} else {
//			for (int i = (int) start.getX(); (i - end.getX()) * actor < 0; i += GameConstant.MOVE_STEP * actor) {
//				rb.mouseMove(i, (int) start.getY());
//				if (i == (int) start.getX()) {
//					GameUtil.delay(GameConstant.DELAY);
//					mousePress();
//				}
//				rb.delay(GameConstant.MOVE_TIME);
//			}
//		}
//		rb.mouseMove((int) end.getX(), (int) end.getY());
//		GameUtil.delay(GameConstant.DELAY);
//		mouseRelease();
//	}
//	public static void mousePressAndReleaseByDD() {
//
//		dd.HIVM_BTN(1);
//		rb.delay(50);
//		dd.HIVM_BTN(2);
//	}
//	public static void mousePressAndReleaseByDDQ(int delay) {
//
//		dd.HIVM_BTN(1);
//		rb.delay(10);
//		dd.HIVM_BTN(2);
//
//	}
//	public static void mouseMoveByDDRadom(int x, int y) {
//
//		dd.HIVM_MOV(x+1+ ran.nextInt(3), y+1+ran.nextInt(3));
//		rb.delay(100);
//	}

//	public static void mouseMoveByRobotAcurate(int x, int y) {
//		rb.mouseMove(x,y);
//	}
//	public static void mousePressAndReleaseByDdQuick(int delay) {
//
//		dd.HIVM_BTN(1);
//		rb.delay(delay);
//		dd.HIVM_BTN(2);
//	}
//	public static void mousePressAndReleaseQuick(int key) {
//			rb.delay(GameConstant.DELAY / 6);
//			dd.HIVM_BTN(1);
//			rb.delay(GameConstant.DELAY / 6);
//			dd.HIVM_BTN(2);
//			rb.delay(GameConstant.DELAY / 6);
//	}
//	public static void mousePressAndReleaseForLongTime(int key,int milliSeconds) {
//		rb.delay(GameConstant.DELAY / 8);
//		dd.HIVM_BTN(1);
//		rb.delay(milliSeconds);
//		dd.HIVM_BTN(2);
//		rb.delay(GameConstant.DELAY / 8);
//	}
//	public static void keyPressAndRelease(int key) {
//			rb.keyPress(key);
//			rb.delay(GameConstant.DELAY/2);
//			rb.keyRelease(key);
//			rb.delay(GameConstant.DELAY);
//			rb.delay(GameConstant.DELAY);
//	}
	
	public static boolean likeEqualColor(Color c1, Color c2) {
		return likeEqualColor(c1, c2, 10);
	}
	public static boolean likeEqualColor(Color c1, Color c2, int minusValue) {
		return (Math.abs(c1.getGreen() - c2.getGreen())
				+ Math.abs(c1.getBlue() - c2.getBlue())
		+ Math.abs(c1.getRed() - c2.getRed())) <= minusValue;
	}
	public static boolean isLargerColor(Color c1, Color c2) {
		return (c1.getRed()+c1.getGreen()+c1.getBlue()
						- c2.getRed()-c2.getGreen()-c2.getBlue())>0;
	}

	public static List<Point> getCommondCards() {
		Point p_support = PointInfo.getInstance().getpSupport();
		Color color;
		Point point;
		PointColor pc;
		List<PointColor> pcList = new LinkedList<>();
		for (int i = 0; i < 5; i++) {
			point = new Point((int) p_support.getX() + i * 257, (int) p_support.getY());
			color = GameUtil.getScreenPixel(point);
			pc = new PointColor(point, color, true);
			pcList.add(pc);
		}
		pcList.sort((pc1, pc2) -> pc1.getColor().getRed() + pc1.getColor().getBlue() + pc1.getColor().getGreen()
				- pc2.getColor().getRed() - pc2.getColor().getBlue() - pc2.getColor().getGreen());
		List<Point> pList = new LinkedList<>();
		Point pTemp;
		Color cTemp;
		for (PointColor pointColor : pcList) {
			cTemp = pointColor.getColor();
			LOGGER.debug(cTemp.getRed() + "_" + cTemp.getGreen() + "_" + cTemp.getBlue());
			pTemp = pointColor.getPoint();
			pTemp.setLocation(pTemp.getX() - 80, pTemp.getY());
			pList.add(pTemp);
		}
		return pList;
	}

	public static String getStackMsg(Throwable e) {
		StringWriter sw = new StringWriter(); 
        e.printStackTrace(new PrintWriter(sw, true)); 
        String strs = sw.toString(); 
		return strs;
	}
	public static String getPreFix() {
		String ROOT_PATH = GameUtil.getValueFromConfig("ROOT_PATH");

		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss\\");
		return System.getenv("OneDrive")
				+ ROOT_PATH + "\\"
				+ sdf.format(date).toString();
	}
	public static String getPicLogsPath() {
		String ROOT_PATH = GameUtil.getValueFromConfig("ROOT_PATH");
		return System.getenv("OneDrive")
				+ ROOT_PATH;
	}
	public static String getPreFixNoDate() {
		String ROOT_PATH = GameUtil.getValueFromConfig("ROOT_PATH");

		return System.getenv("OneDrive")
				+ ROOT_PATH;
	}
	public static ImageIcon getBackGroundPreFix(int width, int length) {
		String rootPath= NativeCp.getOneDriveDir()+ "\\图片\\桌面背景\\";
		String likeName = "";
		File rootFile= new File(rootPath);
		List<File> fileList = new ArrayList<>();
		if (rootFile.isDirectory()) {
			File[] files = rootFile.listFiles();
			int size = files != null ? files.length : 0;
			File tempFile;
			for (int i = 0; i < size; i++) {
				tempFile = files[i];
				if (tempFile.getName().contains("background")) {
					fileList.add(tempFile);
				}
				if (tempFile.getName().contains("like")) {
					likeName = tempFile.getName();
				}
			}
		}else {
			LOGGER.debug("无法获取图片路径！");
		}
		Random rd = new Random(); //创建一个Random类对象实例
        int index = rd.nextInt(fileList.size());
        String picName;
        if("".equals(likeName)){
			picName = fileList.get(index).getName();
		}else{
			picName = likeName;
		}
		ImageIcon im = new ImageIcon(
				System.getenv("OneDrive") + "\\图片\\桌面背景\\"+picName);
		Image me = im.getImage();
		me = me.getScaledInstance(width, length, Image.SCALE_DEFAULT);
		return new ImageIcon(me);
	}
	public static ImageIcon getBackGroundPreFix(int width, int length, String filePath) {
		ImageIcon im = new ImageIcon(filePath);
		Image me = im.getImage();
		me = me.getScaledInstance(width, length, Image.SCALE_DEFAULT);
		return new ImageIcon(me);
	}
	public static void moveToLeftTop() throws AppNeedStopException {

		if(Toolkit.getDefaultToolkit().getScreenSize().width == 2560){
			Point from = new Point(660,416);
			Point to = new Point(660-609,416-383);
			GameUtil.getMymouse().mouseMoveByPoint(from, false, false);
			rb.delay(1000);
			GameUtil.getMymouse().mousePress();
			rb.delay(1000);
			GameUtil.getMymouse().mouseMoveByPoint(to, false, false);

			rb.delay(1000);
			GameUtil.getMymouse().mouseRelease();
		}else{
			GameUtil.getMymouse().mouseMoveByPoint(new Point(339,157), false, false);
			rb.delay(1000);
			GameUtil.getMymouse().mousePress();
			rb.delay(1000);
			GameUtil.getMymouse().mouseMoveByPoint(new Point(50, 30), false, false);

			rb.delay(1000);
			GameUtil.getMymouse().mouseRelease();
		}

	}

	public static void moveToLeftTop(Point fromPoint, Point toPoint) throws AppNeedStopException {
		GameUtil.getMymouse().mouseMoveByPoint(new Point((int) fromPoint.getX(), (int) fromPoint.getY()), false, false);

		rb.delay(GameConstant.DELAY);
		rb.delay(GameConstant.DELAY);
		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mousePress();

		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mouseMoveByPoint(new Point((int) toPoint.getX(), (int) toPoint.getY()), false, false);

		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mouseRelease();
	}
	public static void moveToDestinyPoint(Point from , Point to) throws AppNeedStopException {
		GameUtil.getMymouse().mouseMoveByPoint(new Point((int) from.getX(), (int) from.getY()), false, false);

		rb.delay(GameConstant.DELAY);
		rb.delay(GameConstant.DELAY);
		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mousePress();
		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mouseMoveByPoint(new Point((int) to.getX(), (int) to.getY()), false, false);

		rb.delay(GameConstant.DELAY);
		GameUtil.getMymouse().mouseRelease();
	}
	public static void ctrlV() {
		rb.keyPress(KeyEvent.VK_CONTROL);
		rb.keyPress(KeyEvent.VK_Z);
		rb.delay(GameConstant.DELAY/4);
		rb.keyRelease(KeyEvent.VK_Z);
		rb.keyRelease(KeyEvent.VK_CONTROL);
	}
	public static void delay(int delay) {
		try {
			Thread.sleep(delay);
		} catch (InterruptedException e) {
			LOGGER.error(e.getMessage(),e);
		}
	}
	/**
	 * 两个颜色差
	 *
	 * @return
	 */
	public static int colorMinus(Point pa, Point pb) {
		Color ca = GameUtil.getScreenPixel(pa);
		Color cb = GameUtil.getScreenPixel(pb);
		return ca.getGreen() + ca.getRed() + ca.getBlue() - cb.getGreen() - cb.getRed() - cb.getBlue();
	}
	public static int[] strToIntArray(String ArrayStr,boolean ifSort) {
		int[] intArray;
		if (!"".equals(ArrayStr)) {
			String[] strArray = ArrayStr.split(",");
			int size = strArray.length;
			int len = size;
			for (int i = 0; i < size; i++) {
				if (StringUtils.isBlank(strArray[i])) {
					len-=1;
				}
			}
			intArray = new int[len];
			int count = 0;
			for (int i = 0; i < size; i++) {
				if (StringUtils.isNoneBlank(strArray[i])) {
					intArray[count] = Integer.parseInt(strArray[i]);
					count++;
				}
			}
		}else {
			intArray = new int[0];
		}
		if (ifSort) {
			Arrays.sort(intArray);
		}
		return intArray;
	}
	public static void showPositionAndColor() {
		Point p = GameUtil.getMousePosition();
		Color color = GameUtil.getScreenPixel(p);
		Map<String,String> ShowAndJsonMap =  getShowAndJsonContentByPointAndColor(p, color);
		String jsonText =ShowAndJsonMap.get("jsonText");
		String showText =ShowAndJsonMap.get("showText");
		setSysClipboardText(jsonText);
		JOptionPane.showMessageDialog(null, showText, "坐标颜色", JOptionPane.WARNING_MESSAGE);

	}
	public static int getWeek(Date date){
		int[] weeks = {7,1,2,3,4,5,6};
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if(week_index<0){
			week_index = 0;
		}
		return weeks[week_index];
	}
	/**
	 * 将字符串复制到剪切板。
	 */
	public static void setSysClipboardText(String writeMe) {
		Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
		Transferable tText = new StringSelection(writeMe);
		clip.setContents(tText, null);
	}
	public static void moveToPositionByClipBoard() throws Exception {
		String text = ClipBoardUtil.getSysClipboardText();
		text = text.replaceAll(" ","");
		text = text.replaceAll("\n","");
		text = text.replaceAll("\t","");
		text = text.substring(text.indexOf("{\"x\""),text.indexOf("}")+1);
		if (StringUtils.isNotBlank(text)) {
			Point p = JSONObject.parseObject(text, Point.class);
			// 移动
			GameUtil.getMymouse().mouseMoveByPoint(new Point((int)p.getX(),(int)p.getY()), false, false);

		} else {
			throw new Exception("the json String in clipBord is empty !");
		}

	}
	/**
	 * 根据类型获取字符串
	 * @return Map<String,String> (jsonText/showText)
	 */
	public static Map<String,String> getShowAndJsonContentByPointAndColor(Point p, Color color){
		Map<String,String> map = new HashMap<>();
		String jsonText;
		String showText;
		String rgbStr;
		String pointCode;
		String rgbCode;
		rgbStr = color.getRed() + ";" + color.getGreen() + ";" + color.getBlue();
		pointCode = "{\n" +
				"\t\t\"point\" : {\"x\" : " + (int) p.getX() + ", \"y\" : " + (int) p.getY() + "},\n";
		rgbCode =        "\t\t\"color\" : {\"r\" : " + color.getRed() + ", \"g\" : " + color.getGreen() + ", \"b\" : " + color.getBlue()+"}\n"
				+"}";
		jsonText = pointCode + rgbCode;
		rgbStr = color.getRed() + ";" + color.getGreen() + ";" + color.getBlue();
		showText = "坐标: " + p.getX() + ":" + p.getY() + " 颜色: " + rgbStr;
		map.put("jsonText",jsonText);
		map.put("showText",showText);
		return map;
	}
	public static void main(String[] args) {
		GameUtil.getMymouse().mouseWhell(200);
		GameUtil.delay(5000);
		GameUtil.getMymouse().mouseWhell(200);
		GameUtil.getMymouse().mouseWhell(-1);
		GameUtil.getMymouse().mouseWhell(-1);

		System.out.println(333);
	}
	public static String getValueFromConfig(String key) {
		String fgoArrayStr =  PropertiesUtil.getValueFromTempConfig(key);
		if (StringUtils.isBlank(fgoArrayStr)) {
			fgoArrayStr = PropertiesUtil.getValueFromConfig(key);
		}else {
			fgoArrayStr = "null".equals(fgoArrayStr) ? "" : fgoArrayStr;
			Map<String, String> map = new HashMap<>();
			map.put(key, "");
			PropertiesUtil.setValueForInitTemp(map);
		}
		return fgoArrayStr;
	}

}
